﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace game
{
    public class ModelObject : GameObject
    {
        protected ModelUnit model = null;

        public ModelObject(Scene scene, ModelUnit model, int layerIndex)
            : base(scene, layerIndex)
        {
            this.model = model;
            if (model != null)
            {
                bSphere = model.BSphere;
            }
        }

        public override void DrawOpaque(GameTime gameTime)
        {
            if (model != null)
            {
                foreach (ModelMesh mesh in model.Model.Meshes)
                {
                    //foreach (BasicEffect effect in mesh.Effects)
                    //{
                    //    effect.PreferPerPixelLighting = true;
                    //    //effect.VertexColorEnabled = true;
                    //    effect.EnableDefaultLighting();
                    //    effect.World = model.transforms[mesh.ParentBone.Index] * World;
                    //    effect.View = scene.ActiveCamera.View;
                    //    effect.Projection = scene.ActiveCamera.Projection;
                    //}
                    foreach (Effect effect in mesh.Effects)
                    {
                        //if (this is Asteroid)
                        //{
                        //    if (Input.Keyboard.IsKeyDown(Keys.V))
                        //        //if(Vector3.Distance(scene.ActiveCamera.Position, position) < 300000)
                        //        effect.CurrentTechnique = effect.Techniques["PhongParallaxNormalTextured"];
                        //    //else
                        //    //    effect.CurrentTechnique = effect.Techniques["PhongTextured"];
                        //    else
                        //        effect.CurrentTechnique = effect.Techniques["PhongNormalTextured"];
                        //}
                        //else
                        //{
                        //    effect.CurrentTechnique = effect.Techniques["PhongTextured"];
                        //}

                        Matrix w = model.transforms[mesh.ParentBone.Index] * World;
                        effect.Parameters["gWorld"].SetValue(w);
                        Matrix wInvT;
                        Matrix.Invert(ref w, out wInvT);
                        Matrix.Transpose(ref wInvT, out wInvT);
                        effect.Parameters["gWorldInvT"].SetValue(wInvT);

                        effect.Parameters["gWVP"].SetValue(w * scene.ActiveCamera.View
                            * scene.ActiveCamera.Projection);

                        effect.Parameters["gEyePosW"].SetValue(scene.ActiveCamera.Position);

                        SetLights(effect);
                    }
                    mesh.Draw();
                }
            }
        }

        protected void SetLights(Effect effect)
        {
            
            PointLight curLight = null, ligthChosen1, ligthChosen2;
            float curShortestDist;
            List<PointLight> lights = scene.Lights;

            curShortestDist = float.MaxValue;
            for (int i = 0; i < lights.Count; i++)
            {
                float dist;
                Vector3 lightPos = lights[i].Position;
                Vector3.DistanceSquared(ref position, ref lightPos, out dist);

                if (dist < curShortestDist)
                {
                    curShortestDist = dist;
                    curLight = lights[i];
                }
            }
            if (curLight != null)
            {
                effect.Parameters["gPL1Diff"].SetValue(curLight.Diffuse);
                effect.Parameters["gPL1Pos"].SetValue(curLight.Position);
                effect.Parameters["gPL1Att012"].SetValue(curLight.Attenuation012);
                ligthChosen1 = curLight;
            }
            else
            {
                effect.Parameters["gPL1Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL1Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL1Att012"].SetValue(Vector3.Zero);
                effect.Parameters["gPL2Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL2Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL2Att012"].SetValue(Vector3.Zero);
                effect.Parameters["gPL3Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL3Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL3Att012"].SetValue(Vector3.Zero);
                return;
            }


            curLight = null;
            curShortestDist = float.MaxValue;
            for (int i = 0; i < lights.Count; i++)
            {
                PointLight light = lights[i];
                if (light == ligthChosen1)
                    continue;
                float dist;
                Vector3 lightPos = light.Position;
                Vector3.DistanceSquared(ref position, ref lightPos, out dist);

                if (dist < curShortestDist)
                {
                    curShortestDist = dist;
                    curLight = light;
                }
            }
            if (curLight != null)
            {
                effect.Parameters["gPL2Diff"].SetValue(curLight.Diffuse);
                effect.Parameters["gPL2Pos"].SetValue(curLight.Position);
                effect.Parameters["gPL2Att012"].SetValue(curLight.Attenuation012);
                ligthChosen2 = curLight;
            }
            else
            {
                effect.Parameters["gPL2Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL2Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL2Att012"].SetValue(Vector3.Zero);
                effect.Parameters["gPL3Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL3Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL3Att012"].SetValue(Vector3.Zero);
                return;
            }


            curLight = null;
            curShortestDist = float.MaxValue;
            for (int i = 0; i < lights.Count; i++)
            {
                PointLight light = lights[i];
                if (light == ligthChosen1 || light == ligthChosen2)
                    continue;
                float dist;
                Vector3 lightPos = light.Position;
                Vector3.DistanceSquared(ref position, ref lightPos, out dist);

                if (dist < curShortestDist)
                {
                    curShortestDist = dist;
                    curLight = light;
                }
            }
            if (curLight != null)
            {
                effect.Parameters["gPL3Diff"].SetValue(curLight.Diffuse);
                effect.Parameters["gPL3Pos"].SetValue(curLight.Position);
                effect.Parameters["gPL3Att012"].SetValue(curLight.Attenuation012);
                ligthChosen2 = curLight;
            }
            else
            {
                effect.Parameters["gPL3Diff"].SetValue(Vector4.Zero);
                effect.Parameters["gPL3Pos"].SetValue(Vector3.Zero);
                effect.Parameters["gPL3Att012"].SetValue(Vector3.Zero);
            }
            return;
        }

        public override void DrawWithCustomShader(GameTime gameTime, SingleMatrixShader shader)
        {
            if (model != null)
            {
                model.SetEffect(shader.Effect);
                Matrix viewProj = scene.ActiveCamera.View * scene.ActiveCamera.Projection;

                foreach (ModelMesh mesh in model.Model.Meshes)
                {
                    shader.EP_gWVP.SetValue(Matrix.CreateScale(0.99f) * model.transforms[mesh.ParentBone.Index] * World * viewProj);
                    mesh.Draw();
                }
                model.SetDefaultEffects();
            }
        }
    }
}
